import uthread
import trinity
import service
import cameras

class CameraClient(service.Service):
    __guid__ = 'svc.cameraClient'
    __notifyevents__ = ['OnSetDevice']
    THREAD_CONTEXT = __guid__.split('.')[-1]

    def Run(self, *etc):
        service.Service.Run(self, *etc)
        self.trinityViewMatrix = trinity.TriView()
        self.trinityProjectionMatrix = trinity.TriProjection()
        defaultCamera = cameras.PolarCamera()
        defaultCamera.SetTrinityMatrixObjects(self.trinityViewMatrix, self.trinityProjectionMatrix)
        self.sharedCameras = {'Basic Camera': defaultCamera}
        self.cameraStack = [defaultCamera]
        self.renderJobCreated = False



    def AddSharedCamera(self, cameraName, cameraObj, setActive = False, transitionBehaviors = []):
        cameraObj.SetTrinityMatrixObjects(self.trinityViewMatrix, self.trinityProjectionMatrix)
        self.sharedCameras[cameraName] = cameraObj
        if setActive:
            self.PushActiveCamera(cameraObj, transitionBehaviors)



    def RemoveSharedCamera(self, cameraName):
        if (cameraName in self.sharedCameras):
            cameraObj = self.sharedCameras[cameraName]
            del self.sharedCameras[cameraName]
        else:
            self.LogWarn((('Attempting to remove shared camera ' + cameraName) + " but it doesn't exist in the available cameras!"))



    def GetSharedCamera(self, cameraName):
        if (cameraName in self.sharedCameras):
            return self.sharedCameras[cameraName]



    def PushActiveCamera(self, cameraObj, transitionBehaviors = []):
        cameraObj.SetTrinityMatrixObjects(self.trinityViewMatrix, self.trinityProjectionMatrix)
        if transitionBehaviors:
            uthread.new(self._PushAndTransition, cameraObj, transitionBehaviors).context = 'CameraClient::_PushAndTransitionNewCamera'
        else:
            self.cameraStack.append(cameraObj)
            cameraObj.UpdateProjectionMatrix()
            self._CreateCameraRenderJob()



    def _PushAndTransition(self, cameraObj, transitionBehaviors):
        cameraObj.Update()
        transitionCamera = cameras.TransitionCamera()
        transitionCamera.SetTrinityMatrixObjects(self.trinityViewMatrix, self.trinityProjectionMatrix)
        for transitionbehavior in transitionBehaviors:
            transitionCamera.AddBehavior(transitionbehavior)

        transitionCamera.SetTransitionTargets(self.GetActiveCamera(), cameraObj, pushing=True)
        transitionCamera.Update()
        self.cameraStack.append(transitionCamera)



    def PopActiveCamera(self, transitionBehaviors = []):
        if (len(self.cameraStack) > 1):
            if transitionBehaviors:
                uthread.new(self._PopAndTransition, transitionBehaviors).context = 'CameraClient._PopAndTransition'
            else:
                camObj = self.cameraStack.pop()
                self.GetActiveCamera().UpdateProjectionMatrix()
        self.LogWarn('Attempting to pop the default camera!  Cannot clear the camera stack!')



    def _PopAndTransition(self, transitionBehaviors):
        transitionCamera = cameras.TransitionCamera()
        transitionCamera.SetTrinityMatrixObjects(self.trinityViewMatrix, self.trinityProjectionMatrix)
        for transitionbehavior in transitionBehaviors:
            transitionCamera.AddBehavior(transitionbehavior)

        transitionCamera.SetTransitionTargets(self.GetActiveCamera(), self.cameraStack[-2], pushing=False)
        self.cameraStack.append(transitionCamera)
        transitionCamera.Update()



    def SetDefaultCamera(self, camera, clearStack = True):
        if clearStack:
            self.cameraStack = [camera]
        else:
            self.cameraStack[0] = camera
        self.GetActiveCamera().UpdateProjectionMatrix()
        self._CreateCameraRenderJob()



    def GetDefaultCamera(self):
        return self.cameraStack[0]



    def GetActiveCamera(self):
        return self.cameraStack[-1]



    def OnSetDevice(self):
        self.GetActiveCamera().UpdateProjectionMatrix()



    def _CreateCameraRenderJob(self):
        return 




